#include <windows.h>
#include "Header.h"
#include <stdio.h>

void MonikerTest()
{
    HRESULT hResult;
    IMoniker* lpIMoniker = nullptr;
    IBindCtx* lpIBindCtx = nullptr;
    ULONG chEaten;
    LPCOLESTR lpUserName = L"clsid:DCB56D2A-7639-43C1-A7E2-EE626D3DA689:!Kitty!DragonLi";
    IVariety* lpIVariety = nullptr;

    do
    {
        hResult = CreateBindCtx(0, &lpIBindCtx);
        if (hResult != S_OK) break;

        hResult = MkParseDisplayName(lpIBindCtx, lpUserName, &chEaten, &lpIMoniker);
        if (hResult != S_OK) break;

        hResult = lpIMoniker->BindToObject(lpIBindCtx, nullptr, IID_IVariety, (void**)&lpIVariety);
        if (hResult != S_OK) break;

        lpIVariety->Show();

    } while (FALSE);

    if (lpIVariety)
        lpIVariety->Release();

    if (lpIMoniker)
        lpIMoniker->Release();

    if (lpIBindCtx)
        lpIBindCtx->Release();
}

void MonikerTest2()
{
    HRESULT hResult;
    LPCOLESTR lpUserName = L"clsid:DCB56D2A-7639-43C1-A7E2-EE626D3DA689:!Puppy";
    IDog* lpDog = nullptr;

    do
    {
        hResult = CoGetObject(lpUserName, nullptr, IID_IDog, (void**)&lpDog);
        if (hResult != S_OK) break;

        lpDog->Woof((const unsigned char*)"Hello\r\n");

    } while (FALSE);

    if (lpDog)
        lpDog->Release();
}

void MonikerTest3()
{
    HRESULT hResult;
    IMoniker* lpIMoniker = nullptr;
    IBindCtx* lpIBindCtx = nullptr;
    LPCOLESTR lpUserName = L"clsid:1904BE9D-0377-453E-989A-C8BA4F3F940E:";
    IPig* lpPig = nullptr;

    do
    {
        hResult = CreateBindCtx(0, &lpIBindCtx);
        if (hResult != S_OK) break;

        hResult = CreateClassMoniker(CLSID_ANIMALS, &lpIMoniker);
        if (hResult != S_OK) break;

        hResult = lpIMoniker->BindToObject(lpIBindCtx, nullptr, IID_IPig, (void**)&lpPig);
        if (hResult != S_OK) break;

        lpPig->Oink((const unsigned char*)"Hello\r\n");

    } while (FALSE);

    if (lpPig)
        lpPig->Release();

    if (lpIMoniker)
        lpIMoniker->Release();

    if (lpIBindCtx)
        lpIBindCtx->Release();
}

void MonikerTest4()
{
    HRESULT hResult;
    LPCOLESTR lpUserName = L"clsid:DCB56D2A-7639-43C1-A7E2-EE626D3DA689:!Puppy";
    IDog* lpDog = nullptr;
    IPersistFile* lpIPersistFile = nullptr;

    do
    {
        hResult = CoGetObject(lpUserName, nullptr, IID_IDog, (void**)&lpDog);
        if (hResult != S_OK) break;

        lpDog->Woof((const unsigned char*)"Hello\r\n");

        hResult = lpDog->QueryInterface(IID_IPersistFile, (void**)&lpIPersistFile);
        if (hResult != S_OK) break;

        lpIPersistFile->Save(L"..\\Bin\\FILE.bin", TRUE);

    } while (FALSE);

    if (lpIPersistFile)
        lpIPersistFile->Release();

    if (lpDog)
        lpDog->Release();
}

void MonikerTest5()
{
    HRESULT hResult;
    LPCOLESTR lpUserName = L"clsid:1904BE9D-0377-453E-989A-C8BA4F3F940E:";
    IDog* lpDog = nullptr;
    IPersistFile* lpIPersistFile = nullptr;

    do
    {
        hResult = CoGetObject(lpUserName, nullptr, IID_IDog, (void**)&lpDog);
        if (hResult != S_OK) break;

        lpDog->Woof((const unsigned char*)"Hello\r\n");

        hResult = lpDog->QueryInterface(IID_IPersistFile, (void**)&lpIPersistFile);
        if (hResult != S_OK) break;

        lpIPersistFile->Load(L"..\\Bin\\FILE.bin", TRUE);

        lpDog->Woof((const unsigned char*)"Hello\r\n");

    } while (FALSE);

    if (lpIPersistFile)
        lpIPersistFile->Release();

    if (lpDog)
        lpDog->Release();
}

int main()
{
    IDog* lpDog = nullptr;
    ICat* lpCat = nullptr;
    IPig* lpPig = nullptr;
    IUnknown* lpUnknown = nullptr;
    HRESULT hResult;

    CoInitialize(nullptr);

    do
    {
        MonikerTest();
        MonikerTest2();
        MonikerTest3();
        MonikerTest4();
        MonikerTest5();
        if (1) break;

        hResult = CoGetClassObject(CLSID_ANIMALS, CLSCTX_INPROC, nullptr,
            IID_IUnknown, (void**)&lpUnknown);
        if (S_OK != hResult) break;

        hResult = CoGetClassObject(CLSID_ANIMALS, CLSCTX_INPROC, nullptr,
            IID_IDog, (void**)&lpDog);
        if (S_OK != hResult) break;

        hResult = CoCreateInstance(CLSID_ANIMALS, nullptr, CLSCTX_INPROC,
            IID_ICat, (void**)&lpCat);
        if (S_OK != hResult) break;

        hResult = CoCreateInstance(CLSID_ANIMALS, nullptr, CLSCTX_INPROC,
            IID_IPig, (void**)&lpPig);
        if (S_OK != hResult) break;

        lpDog->Woof((const unsigned char*)"Hello\r\n");
        lpCat->Meow((const unsigned char*)"Hello\r\n");
        lpPig->Oink((const unsigned char*)"Hello\r\n");

    } while (FALSE);

    if (lpPig)
    {
        lpPig->Release();
    }

    if (lpCat)
    {
        lpCat->Release();
    }

    if (lpDog)
    {
        lpDog->Release();
    }

    if (lpUnknown)
    {
        lpUnknown->Release();
    }

    CoFreeUnusedLibraries();

    CoUninitialize();

    return 0;
}